package hydrap2p.gui;

import java.awt.Component;
import java.text.DecimalFormat;
import java.util.ArrayList;

import javax.swing.BorderFactory;
import javax.swing.JProgressBar;
import javax.swing.JTable;
import javax.swing.SwingConstants;
import javax.swing.table.DefaultTableCellRenderer;
import javax.swing.table.DefaultTableModel;

public class FileTransferTableModel extends DefaultTableModel {

	private static final ColumnContext[] columnArray = { // This provides a list of the columns for the table in the FileTransferPanel; provides column name and data type
			new ColumnContext("Status", String.class, false), // The current activity summary of the file transfer, such as "Paused", "Active", etc.
			new ColumnContext("Priority", String.class, false), // The order of priority for file transfers (1 is highest, 2 is next-highest, etc.)
			new ColumnContext("Name", String.class, false), // The name of the file being transferred
			new ColumnContext("Size", Long.class, false), // The file size in bytes
			new ColumnContext("Progress", Integer.class, false), // The number of bytes downloaded / the total number of bytes in the file
			new ColumnContext("Down Speed", Long.class, false), // The number of bytes downloaded / the total time the file transfer has been allowed to download (in bytes/s)
			new ColumnContext("Up Speed", Long.class, false) // The number of bytes uploaded / the total time the file transfer has been allowed to upload (in bytes/s)
	};

	/**
	 * This method adds a file transfer to the FileTransferPanel's table.
	 * @param gdl - the object representing the file transfer itself
	 */
	public void addListing(GUIDownloadListing gdl) {
//		Object[] obj = { gdl.getStatus(), gdl.getPriority(), gdl.getName(),
//				gdl.getSize(), gdl.getProgress(), new Long(0), new Long(0) }; // Parses the file transfer's information into the relevant columns
		Object[] obj = { gdl.getStatus(), gdl.getPriorityString(), gdl.getName(),
				gdl.getSize(), gdl.getProgress(), gdl.getDownloadSpeed(), new Long(0) }; // Parses the file transfer's information into the relevant columns
		super.addRow(obj); // Adds the new row to the table
	}
	
	public boolean isCellEditable(int row, int col) {
		return columnArray[col].isEditable;
	}

	public Class<?> getColumnClass(int modelIndex) {
		return columnArray[modelIndex].columnClass;
	}

	public int getColumnCount() {
		return columnArray.length;
	}

	public String getColumnName(int modelIndex) {
		return columnArray[modelIndex].columnName;
	}

	private static class ColumnContext {
		public final String columnName;
		public final Class columnClass;
		public final boolean isEditable;

		public ColumnContext(String columnName, Class columnClass,
				boolean isEditable) {
			this.columnName = columnName;
			this.columnClass = columnClass;
			this.isEditable = isEditable;
		}
	}
}

class BytesRenderer extends DefaultTableCellRenderer {
	public Component getTableCellRendererComponent(JTable table, Object value,
			boolean isSelected, boolean hasFocus, int row, int column) {
		setHorizontalAlignment(SwingConstants.LEFT);

		// a list of labels to put on the end of the byte count
		ArrayList<String> byteTerms = new ArrayList<String>();
		byteTerms.add("B");
		byteTerms.add("KB");
		byteTerms.add("MB");
		byteTerms.add("GB");
		byteTerms.add("TB");
		byteTerms.add("PB");

		// figure out the best way to represent this
		int currentTerm = 0;
		Double count = new Double((Long) value);
		while (count >= 1024 && currentTerm + 1 < byteTerms.size()) {
			count /= 1024;
			currentTerm++;
		}

		// get rid of the decimal place if it's just bytes
		String stringVal = String.valueOf((Long) value);
		if (currentTerm != 0) {
			DecimalFormat twoDForm = new DecimalFormat("#.##");
			stringVal = String.valueOf(twoDForm.format(count));
		}
		stringVal = stringVal + " " + byteTerms.get(currentTerm);

		// this.setText(stringVal);
		super.getTableCellRendererComponent(table, stringVal, isSelected,
				hasFocus, row, column);
		return this;
	}
}

class SpeedRenderer extends DefaultTableCellRenderer {
	public Component getTableCellRendererComponent(JTable table, Object value,
			boolean isSelected, boolean hasFocus, int row, int column) {
		setHorizontalAlignment(SwingConstants.LEFT);

		// a list of labels to put on the end of the byte count
		ArrayList<String> byteTerms = new ArrayList<String>();
		byteTerms.add("B/s");
		byteTerms.add("KB/s");
		byteTerms.add("MB/s");
		byteTerms.add("GB/s");
		byteTerms.add("TB/s");
		byteTerms.add("PB/s");

		// figure out the best way to represent this
		// note that the speeds will be represented in bits because that's how
		// everything is done, even though the actual speed data is in bytes
		int currentTerm = 0;
		Double count = new Double((Long) value);
		while (count > 1024) {
			count /= 1024;
			currentTerm++;
		}

		// get rid of the decimal place if it's just bytes
		String stringVal = String.valueOf((Long) value);
		if (currentTerm != 0) {
			DecimalFormat twoDForm = new DecimalFormat("#.##");
			stringVal = String.valueOf(twoDForm.format(count));
		}
		stringVal = stringVal + " " + byteTerms.get(currentTerm);

		// this.setText(stringVal);
		super.getTableCellRendererComponent(table, stringVal, isSelected,
				hasFocus, row, column);
		return this;
	}
}

class ProgressRenderer extends DefaultTableCellRenderer {
	private final JProgressBar b = new JProgressBar(0, 100);

	public ProgressRenderer() {
		super();
		setOpaque(true);
		b.setBorder(BorderFactory.createEmptyBorder(1, 1, 1, 1));
	}

	public Component getTableCellRendererComponent(JTable table, Object value,
			boolean isSelected, boolean hasFocus, int row, int column) {
		Integer i = (Integer) value;
		String text = "Done";
		if (i < 0) {
			text = "Canceled";
		} else if (i < 100) {
			b.setValue(i);
			return b;
		}
		super.getTableCellRendererComponent(table, text, isSelected, hasFocus,
				row, column);
		return this;
	}
}
